#include <stdio.h>

typedef char Item;
typedef struct node* link;

struct node {
    Item item;
    link l;
    link r;
};

void trav_pre(link h, void (*visit)(link));
void trav_in(link h, void (*visit)(link));
void trav_post(link h, void (*visit)(link));
void visit(link node);


int main(int argc, char* argv[]) {
    struct node root;
    struct node dNode;
    struct node hNode;
    struct node bNode;
    struct node fNode;
    struct node aNode;
    struct node cNode;
    struct node gNode;





    root.item = 'E';
    root.l = &dNode;
    root.r = &hNode;

    dNode.item = 'D';
    dNode.l = &bNode;
    dNode.r = NULL;
    hNode.item = 'H';
    hNode.l = &fNode;
    hNode.r = NULL;

    bNode.item = 'B';
    bNode.l = &aNode;
    bNode.r = &cNode;
    fNode.item = 'F';
    fNode.l = NULL;
    fNode.r = &gNode;

    aNode.item = 'A';
    aNode.l = NULL;
    aNode.r = NULL;
    cNode.item = 'C';
    cNode.l = NULL;
    cNode.r = NULL;
    gNode.item = 'G';
    gNode.l = NULL;
    gNode.r = NULL;

    trav_pre(&root, visit);
    printf("\n");
    trav_in(&root, visit);
    printf("\n");
    trav_post(&root, visit);
    printf("\n");

    return 0;
}

/**
 * Program 5.14 Recursive tree traversal
 * ---------------------------------------------------------------
 * This recursive function takes a link to a tree as an argument and 
 * calls the function visit with each of the nodes in the tree as argument.
 * As is, the function implements a preorder traversal; 
 * if we move the call to visit between the recursive calls, we have an inorder traversal;
 * and if we move the call to visit after the recursive calls, we have a postorder traversal.
 */
void trav_pre(link h, void (*visit)(link)){
    if (h == NULL) {
        return ;
    }
    (*visit)(h);
    trav_pre(h->l, visit);
    trav_pre(h->r, visit);
}

void trav_in(link h, void (*visit)(link)){
    if (h == NULL) {
        return ;
    }
    trav_in(h->l, visit);
    (*visit)(h);
    trav_in(h->r, visit);
}

void trav_post(link h, void (*visit)(link)){
    if (h == NULL) {
        return ;
    }
    trav_post(h->l, visit);
    trav_post(h->r, visit);
    (*visit)(h);
}

void visit(link node){
    printf("%c ", node->item);
}